home *** CD-ROM | disk | FTP | other *** search
/ Cracking 2 / Cracking II..iso / Kompresni & kodovaci programy / ucl-0.91 / examples / uclpack.c < prev   
C/C++ Source or Header  |  2000-02-23  |  17KB  |  634 lines

  1. /* uclpack.c -- example program: a simple file packer
  2.  
  3.    This file is part of the UCL real-time data compression library.
  4.  
  5.    Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer
  6.  
  7.    The UCL library is free software; you can redistribute it and/or
  8.    modify it under the terms of the GNU General Public License as
  9.    published by the Free Software Foundation; either version 2 of
  10.    the License, or (at your option) any later version.
  11.  
  12.    The UCL library is distributed in the hope that it will be useful,
  13.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.    GNU General Public License for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with the UCL library; see the file COPYING.
  19.    If not, write to the Free Software Foundation, Inc.,
  20.    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21.  
  22.    Markus F.X.J. Oberhumer
  23.    markus.oberhumer@jk.uni-linz.ac.at
  24.  */
  25.  
  26.  
  27. /*************************************************************************
  28. // NOTE: this is an example program, so do not use to backup your data
  29. //
  30. // This program lacks things like sophisticated file handling but is
  31. // pretty complete regarding compression - it should provide a good
  32. // starting point for adaption for you applications.
  33. **************************************************************************/
  34.  
  35. #include <ucl/ucl.h>
  36. #include "lutil.h"
  37.  
  38. static const char *progname = NULL;
  39.  
  40. static unsigned long total_in = 0;
  41. static unsigned long total_out = 0;
  42. static ucl_bool opt_debug = 0;
  43.  
  44. /* don't compute or verify checksum, always use fast decompressor */
  45. static ucl_bool opt_fast = 0;
  46.  
  47. /* magic file header for compressed files */
  48. static const unsigned char magic[7] =
  49.     { 0x00, 0xe9, 0x55, 0x43, 0x4c, 0xff, 0x1a };
  50.  
  51.  
  52. /*************************************************************************
  53. // file IO
  54. **************************************************************************/
  55.  
  56. ucl_uint xread(FILE *f, ucl_voidp buf, ucl_uint len, ucl_bool allow_eof)
  57. {
  58.     ucl_uint l;
  59.  
  60.     l = ucl_fread(f,buf,len);
  61.     if (l > len)
  62.     {
  63.         fprintf(stderr,"\nsomething's wrong with your C library !!!\n");
  64.         exit(1);
  65.     }
  66.     if (l != len && !allow_eof)
  67.     {
  68.         fprintf(stderr,"\nread error - premature end of file\n");
  69.         exit(1);
  70.     }
  71.     total_in += l;
  72.     return l;
  73. }
  74.  
  75. ucl_uint xwrite(FILE *f, const ucl_voidp buf, ucl_uint len)
  76. {
  77.     if (f != NULL && ucl_fwrite(f,buf,len) != len)
  78.     {
  79.         fprintf(stderr,"\nwrite error  (disk full ?)\n");
  80.         exit(1);
  81.     }
  82.     total_out += len;
  83.     return len;
  84. }
  85.  
  86.  
  87. int xgetc(FILE *f)
  88. {
  89.     unsigned char c;
  90.     xread(f,(ucl_bytep) &c,1,0);
  91.     return c;
  92. }
  93.  
  94. void xputc(FILE *f, int c)
  95. {
  96.     unsigned char cc = (unsigned char) c;
  97.     xwrite(f,(ucl_bytep) &cc,1);
  98. }
  99.  
  100. /* read and write portable 32-bit integers */
  101.  
  102. ucl_uint32 xread32(FILE *f)
  103. {
  104.     unsigned char b[4];
  105.     ucl_uint32 v;
  106.  
  107.     xread(f,b,4,0);
  108.     v  = (ucl_uint32) b[3] <<  0;
  109.     v |= (ucl_uint32) b[2] <<  8;
  110.     v |= (ucl_uint32) b[1] << 16;
  111.     v |= (ucl_uint32) b[0] << 24;
  112.     return v;
  113. }
  114.  
  115. void xwrite32(FILE *f, ucl_uint32 v)
  116. {
  117.     unsigned char b[4];
  118.  
  119.     b[3] = (unsigned char) (v >>  0);
  120.     b[2] = (unsigned char) (v >>  8);
  121.     b[1] = (unsigned char) (v >> 16);
  122.     b[0] = (unsigned char) (v >> 24);
  123.     xwrite(f,b,4);
  124. }
  125.  
  126.  
  127. /* util */
  128. static ucl_uint get_overhead(int method, ucl_uint size)
  129. {
  130.     if (method == 0x2B || method == 0x2D)
  131.         return size / 8 + 256;
  132.     return 0;
  133. }
  134.  
  135.  
  136. static char method_name[64];
  137.  
  138. static ucl_bool set_method_name(int method, int level)
  139. {
  140.     method_name[0] = 0;
  141.     if (level < 1 || level > 10)
  142.         return 0;
  143.     if (method == 0x2B)
  144.         sprintf(method_name,"NRV2B-99/%d", level);
  145.     else if (method == 0x2D)
  146.         sprintf(method_name,"NRV2D-99/%d", level);
  147.     else
  148.         return 0;
  149.     return 1;
  150. }
  151.  
  152.  
  153. /*************************************************************************
  154. // compress
  155. //
  156. // possible improvement: we could use overlapping compression to
  157. //   save some memory - see overlap.c. This would require some minor
  158. //   changes in the decompression code as well, because if a block
  159. //   turns out to be incompressible we would still have to store it in its
  160. //   compressed (slightly enlarged) form because the original (uncompressed)
  161. //   data would have been lost during the overlapping compression.
  162. **************************************************************************/
  163.  
  164. int do_compress(FILE *fi, FILE *fo, int method, int level, ucl_uint block_size)
  165. {
  166.     int r = 0;
  167.     ucl_byte *in = NULL;
  168.     ucl_byte *out = NULL;
  169.     ucl_uint in_len;
  170.     ucl_uint out_len;
  171.     ucl_uint32 flags = opt_fast ? 0 : 1;
  172.     ucl_uint32 checksum;
  173.     ucl_uint overhead = 0;
  174.  
  175.     total_in = total_out = 0;
  176.  
  177. /*
  178.  * Step 1: write magic header, flags & block size, init checksum
  179.  */
  180.     xwrite(fo,magic,sizeof(magic));
  181.     xwrite32(fo,flags);
  182.     xputc(fo,method);           /* compression method */
  183.     xputc(fo,level);            /* compression level */
  184.     xwrite32(fo,block_size);
  185.     checksum = ucl_adler32(0,NULL,0);
  186.  
  187. /*
  188.  * Step 2: allocate compression buffers and work-memory
  189.  */
  190.     overhead = get_overhead(method,block_size);
  191.     in = ucl_malloc(block_size);
  192.     out = ucl_malloc(block_size + overhead);
  193.     if (in == NULL || out == NULL)
  194.     {
  195.         printf("%s: out of memory\n", progname);
  196.         r = 1;
  197.         goto err;
  198.     }
  199.  
  200. /*
  201.  * Step 3: process blocks
  202.  */
  203.     for (;;)
  204.     {
  205.         /* read block */
  206.         in_len = xread(fi,in,block_size,1);
  207.         if (in_len <= 0)
  208.             break;
  209.  
  210.         /* update checksum */
  211.         if (flags & 1)
  212.             checksum = ucl_adler32(checksum,in,in_len);
  213.  
  214.         /* compress block */
  215.         r = UCL_E_ERROR;
  216.         if (method == 0x2B)
  217.             r = ucl_nrv2b_99_compress(in,in_len,out,&out_len,0,level,NULL,NULL);
  218.         else if (method == 0x2D)
  219.             r = ucl_nrv2d_99_compress(in,in_len,out,&out_len,0,level,NULL,NULL);
  220.         if (r != UCL_E_OK || out_len > in_len + get_overhead(method,in_len))
  221.         {
  222.             /* this should NEVER happen */
  223.             printf("internal error - compression failed: %d\n", r);
  224.             r = 2;
  225.             goto err;
  226.         }
  227.  
  228.         /* write uncompressed block size */
  229.         xwrite32(fo,in_len);
  230.  
  231.         if (out_len < in_len)
  232.         {
  233.             /* write compressed block */
  234.             xwrite32(fo,out_len);
  235.             xwrite(fo,out,out_len);
  236.         }
  237.         else
  238.         {
  239.             /* not compressible - write uncompressed block */
  240.             xwrite32(fo,in_len);
  241.             xwrite(fo,in,in_len);
  242.         }
  243.     }
  244.  
  245.     /* write EOF marker */
  246.     xwrite32(fo,0);
  247.  
  248.     /* write checksum */
  249.     if (flags & 1)
  250.         xwrite32(fo,checksum);
  251.  
  252.     r = 0;
  253. err:
  254.     ucl_free(out);
  255.     ucl_free(in);
  256.     return r;
  257. }
  258.  
  259.  
  260. /*************************************************************************
  261. // decompress / test
  262. //
  263. // We are using overlapping (in-place) decompression to save some
  264. // memory - see overlap.c.
  265. **************************************************************************/
  266.  
  267. int do_decompress(FILE *fi, FILE *fo)
  268. {
  269.     int r = 0;
  270.     ucl_byte *buf = NULL;
  271.     ucl_uint buf_len;
  272.     unsigned char m [ sizeof(magic) ];
  273.     ucl_uint32 flags;
  274.     int method;
  275.     int level;
  276.     ucl_uint block_size;
  277.     ucl_uint32 checksum;
  278.     ucl_uint overhead = 0;
  279.  
  280.     total_in = total_out = 0;
  281.  
  282. /*
  283.  * Step 1: check magic header, read flags & block size, init checksum
  284.  */
  285.     if (xread(fi,m,sizeof(magic),1) != sizeof(magic) ||
  286.         memcmp(m,magic,sizeof(magic)) != 0)
  287.     {
  288.         printf("%s: header error - this file is not compressed by uclpack\n", progname);
  289.         r = 1;
  290.         goto err;
  291.     }
  292.     flags = xread32(fi);
  293.     method = xgetc(fi);
  294.     level = xgetc(fi);
  295.     block_size = xread32(fi);
  296.     overhead = get_overhead(method,block_size);
  297.     if (overhead == 0 || !set_method_name(method, level))
  298.     {
  299.         printf("%s: header error - invalid method %d (level %d)\n",
  300.                 progname, method, level);
  301.         r = 2;
  302.         goto err;
  303.     }
  304.     if (block_size < 1024 || block_size > 8*1024*1024L)
  305.     {
  306.         printf("%s: header error - invalid blo